/**
 * TabVD is a Virtual Desktop Client/Server designed specifically for connecting
 * from Tablet like devices.
 *
 * Copyright (C) 2011 Subhabrata Ghosh
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * PropertiesConfiguration.cpp
 *
 *  Created on: May 25, 2011
 *      Author: subhagho
 */

#include "PropertiesConfiguration.h"

namespace tabvd {

    PropertiesConfiguration::PropertiesConfiguration(const std::string* deffile) {
        this->deffile = deffile; 
    }

    PropertiesConfiguration::~PropertiesConfiguration() {
        if (filename)
            delete filename;
    }

    void PropertiesConfiguration::save() {
        save(*filename);
    }

    void PropertiesConfiguration::save(const std::string filename) {
        try {
            std::string buffer;
            std::ofstream stream(filename.c_str(), std::ofstream::trunc);

            if (stream.good()) {
                // Print the configuration header section...
                buffer.append("#\n#\n");
                buffer.append("# Configuration : ").append(filename).append("\n");
                buffer.append("# Created By : ").append(getenv("USER")).append("\n");
                DateTime *dt = new DateTime();
                buffer.append("# Date : ").append(*dt->toString()).append("\n"); 
                buffer.append("#\n#\n");

                stream.write(buffer.c_str(), buffer.size());

                // Start printing the configuration elements....
                for (Config::iterator it = config->begin(); it != config->end();
                        ++it) {
                    if (buffer.size() > 0)
                        buffer.clear();
                    ConfigValue value = it->second;
                    buffer.append(it->first).append("=").append(it->second.getvalue()).append(
                            "\n");
                    stream.write(buffer.c_str(), buffer.size());
                    if (!stream.good()) {
                        throw Exception(
                                "Error writing PropertiesConfiguration to file ["
                                + filename + "]");
                    }
                }
            }
            stream.close();
        } catch (Exception &e) {
            state = STATE_ERROR;
            throw e;
        } catch (...) {
            state = STATE_ERROR;
            throw Exception(
                    "Error saving PropertiesConfiguration to file [" + filename
                    + "]");
        }
    }

    void PropertiesConfiguration::init(const std::string filename) {
        if (!cdefs)
            if(!loaddefs(*deffile))
                throw Exception("Error loading configuration settings.");

        this->filename = new std::string(filename);
        try {
            int buffsz = 1024;
            char buffer[buffsz];

            std::ifstream stream(this->filename->c_str(), std::fstream::in);
            while (true) {
                stream.getline(buffer, buffsz);

                if (stream.eof()) {
                    if (stream.gcount() > 0) {
                        parseline(buffer);
                    }
                    break;
                }
                if (!stream.good()) {
                    throw Exception("Error during reading file [" + filename + "]");
                }
                parseline(buffer);
            }
            stream.close();
            state = STATE_OK;
        } catch (Exception &e) {
            state = STATE_ERROR;
            throw e;
        } catch (...) {
            state = STATE_ERROR;
            throw Exception(
                    "Error initializing PropertiesConfiguration from file ["
                    + filename + "]");
        }
    }

    void PropertiesConfiguration::parseline(const char* line) {
        std::string lines(line);
        size_t cmnt = lines.find("#");
        if (cmnt != std::string::npos){
            lines = lines.substr(0, cmnt);
        }
        size_t found = lines.find('=', 0);
        if (found != std::string::npos) {
            std::string key = lines.substr(0, found);
            std::string val = lines.substr(found + 1);
            if (key.length() > 0 && val.length() > 0){
                if (cdefs->count(key) > 0) {
                    ConfigElement ce = cdefs->at(key);
                    set(key, val);
                }
            }
        }
    }
}
